/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package com.aternity.vbd.ui;

import com.aternity.vbd.collect.ApplicationDao;
import com.aternity.vbd.collect.feedback.FeedbackData;
import com.aternity.vbd.collect.feedback.FeedbackService;
import com.aternity.vbd.mgmt.events.ConnectionSucceededEvent;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
import dnl.utils.swing.PopupUtils;
import dnl.utils.swing.WindowUtils;
import org.jdesktop.swingx.JXTable;
import org.jdesktop.swingx.decorator.HighlighterFactory;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.data.gantt.Task;
import org.jfree.data.gantt.TaskSeries;
import org.jfree.data.gantt.TaskSeriesCollection;
import org.jfree.data.time.SimpleTimePeriod;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import java.awt.event.ActionEvent;
import java.util.Collections;
import java.util.Date;
import java.util.List;

/**
 * @author Daniel Orr
 */
@Component
public class FeedbackPanel extends javax.swing.JPanel {

    private static final Logger logger = LoggerFactory.getLogger(FeedbackPanel.class);

    @Autowired
    EventBus eventBus;

    @Autowired
    FeedbackService feedbackService;

    @Autowired
    ApplicationDao applicationDao;

    private FeedbackEditingDialog feedbackEditingDialog = new FeedbackEditingDialog(getWindowAncestor(), true);


    /**
     * Creates new form FeedbackPanel
     */
    public FeedbackPanel() {
        initComponents();

        JPopupMenu pop = getPopupMenu();
        PopupUtils.addPopup(getFeedbackDataTable(), pop);
        getFeedbackDataTable().setShowGrid(false, false);
        getFeedbackDataTable().addHighlighter(HighlighterFactory.createSimpleStriping());
    }

    private JPopupMenu getPopupMenu() {
        JPopupMenu pop = new JPopupMenu();
        JMenuItem insertFeedbackMenu = new JMenuItem(new AbstractAction("New") {
            @Override
            public void actionPerformed(ActionEvent e) {
                insertNewFeedback();
            }
        });
        JMenuItem editFeedbackMenu = new JMenuItem(new AbstractAction("Edit") {
            @Override
            public void actionPerformed(ActionEvent e) {
                final FeedbackData feedbackData = getSelectedFeedbackData();
                editFeedback(feedbackData);
            }
        });
        JMenuItem deleteFeedbackMenu = new JMenuItem(new AbstractAction("Delete") {
            @Override
            public void actionPerformed(ActionEvent e) {
                deleteFeedback();
            }
        });
        pop.add(insertFeedbackMenu);
        pop.add(editFeedbackMenu);
        pop.add(deleteFeedbackMenu);
        return pop;
    }

    public FeedbackData getSelectedFeedbackData() {
        final int selectedRow = getFeedbackDataTable().getSelectedRow();
        FeedbackTableModel feedbackTableModel = (FeedbackTableModel) getFeedbackDataTable().getModel();
        final FeedbackData dataAtRow = feedbackTableModel.getDataAtRow(selectedRow);
        //System.out.println("selectedRow: " + selectedRow + ", " + dataAtRow.getApp());
        return dataAtRow;
    }

    @PostConstruct
    public void init() {
        feedbackEditingDialog.setApplicationDao(applicationDao);
    }

    @Subscribe
    public void onConnectionSuccess(ConnectionSucceededEvent connectionSucceededEvent) {
//        if(!connectionSucceededEvent.getDbStatus().equals(DbStatus.TABLES_EXIST)){
//            return;
//        }
//        refreshData();
//        feedbackEditingDialog.refreshData();
    }

    public void insertNewFeedback() {
        feedbackEditingDialog.setFeedbackData(new FeedbackData());
        WindowUtils.centerWindowRelative(feedbackEditingDialog, getWindowAncestor());
        feedbackEditingDialog.setVisible(true);
        if (!feedbackEditingDialog.wasCancelled()) {
            final FeedbackData feedbackData = feedbackEditingDialog.getFeedbackData();
            feedbackService.insertFeedback(feedbackData);
            refreshData();
        }
    }

    public void deleteFeedback() {
        final FeedbackData selectedFeedbackData = getSelectedFeedbackData();
        logger.info("Deleting feedback with id {}", selectedFeedbackData.getId());
        feedbackService.deleteFeedback(selectedFeedbackData);
        refreshData();
    }

    public void editFeedback(FeedbackData feedbackData) {
        logger.info("Editing feedback with id {}", feedbackData.getId());
        feedbackEditingDialog.setFeedbackData(feedbackData.copy());
        WindowUtils.centerWindowRelative(feedbackEditingDialog, getWindowAncestor());
        feedbackEditingDialog.setVisible(true);
        if (!feedbackEditingDialog.wasCancelled()) {
            final FeedbackData editedFeedbackData = feedbackEditingDialog.getFeedbackData();
            if (!editedFeedbackData.equals(feedbackData)) {
                feedbackService.updateFeedback(editedFeedbackData);
            }
            refreshData();
        }
    }


    public void refreshData() {
        logger.info("refreshData()");
        final List<FeedbackData> feedbacks = feedbackService.getFeedbacks();
        FeedbackTableModel tm = new FeedbackTableModel(feedbacks);
        getFeedbackDataTable().setModel(tm);
        final ChartPanel timeChart = getTimeChart();
        chartJP.removeAll();
        chartJP.add(timeChart);
        chartJP.revalidate();
    }

    private JXTable getFeedbackDataTable() {
        return (JXTable) feedbackDataTable;
    }

    /**
     * This method is called from within the constructor to initialize the form. WARNING: Do NOT modify this
     * code. The content of this method is always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jSplitPane1 = new javax.swing.JSplitPane();
        jScrollPane1 = new javax.swing.JScrollPane();
        feedbackDataTable = new org.jdesktop.swingx.JXTable();
        chartJP = new javax.swing.JPanel();

        setLayout(new java.awt.BorderLayout());

        jSplitPane1.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);

        feedbackDataTable.setModel(new FeedbackTableModel());
        jScrollPane1.setViewportView(feedbackDataTable);

        jSplitPane1.setRightComponent(jScrollPane1);

        chartJP.setLayout(new java.awt.BorderLayout());
        jSplitPane1.setLeftComponent(chartJP);

        add(jSplitPane1, java.awt.BorderLayout.CENTER);
    }// </editor-fold>//GEN-END:initComponents


    private ChartPanel getTimeChart() {
        final List<FeedbackData> allFeedbacks = feedbackService.getAllFeedbacks();
        final TaskSeries s1 = new TaskSeries("");
        for (FeedbackData feedbackData : allFeedbacks) {
            //RegularTimePeriod tp = new
            s1.add(new Task(feedbackData.getApp()+"/"+feedbackData.getActivity(),
                    new SimpleTimePeriod(feedbackData.getStartTime(),feedbackData.getEndTime())));

        }
        final TaskSeriesCollection dataset = new TaskSeriesCollection();
        dataset.add(s1);

        final JFreeChart chart = ChartFactory.createGanttChart(
                "Feedbacks in Timeline",  // chart title
                "App/Activity",              // domain axis label
                "Date",              // range axis label
                dataset,             // data
                false,                // include legend
                true,                // tooltips
                false                // urls
        );

        final ChartPanel chartPanel = new ChartPanel(chart);
        return chartPanel;
    }

    private class FeedbackTableModel extends AbstractTableModel {

        List<FeedbackData> feedbackDatas = Collections.emptyList();

        private FeedbackTableModel() {
        }

        private FeedbackTableModel(List<FeedbackData> feedbackDatas) {
            this.feedbackDatas = feedbackDatas;
        }

        FeedbackData getDataAtRow(int row) {
            return feedbackDatas.get(row);
        }

        @Override
        public int getRowCount() {
            return feedbackDatas.size();
        }

        @Override
        public int getColumnCount() {
            return 6;
        }

        @Override
        public Class<?> getColumnClass(int columnIndex) {
            switch (columnIndex) {
                case 0:
                    return String.class;
                case 1:
                    return String.class;
                case 2:
                    return Integer.class;
                case 3:
                    return Date.class;
                case 4:
                    return Date.class;
                case 5:
                    return Boolean.class;
            }
            return null;
        }

        @Override
        public String getColumnName(int column) {
            switch (column) {
                case 0:
                    return "App";
                case 1:
                    return "Activity";
                case 2:
                    return "Activity ID";
                case 3:
                    return "Start";
                case 4:
                    return "End";
                case 5:
                    return "Problem?";
            }
            return null;
        }

        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            FeedbackData feedbackData = feedbackDatas.get(rowIndex);
            switch (columnIndex) {
                case 0:
                    return feedbackData.getApp();
                case 1:
                    return feedbackData.getActivity();
                case 2:
                    return feedbackData.getActivityId();
                case 3:
                    return feedbackData.getStartTime();
                case 4:
                    return feedbackData.getEndTime();
                case 5:
                    return feedbackData.isProblem();
            }
            return null;
        }
    }

    private JFrame getWindowAncestor() {
        return (JFrame) SwingUtilities.getWindowAncestor(this);
    }

    @Override
    public String toString() {
        return "FeedbackPanel{}";
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JPanel chartJP;
    private javax.swing.JTable feedbackDataTable;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JSplitPane jSplitPane1;
    // End of variables declaration//GEN-END:variables
}
